Skip to content

Exercises

Icon Buttons

Let's build an IconButton component!

We'll use the react-feather package to provide the icons. As a quick refresher, here's how we render an icon from react-feather:

import { Award } from 'react-feather';
<Award size={32} />

Acceptance Criteria:

  • We should be able to pass any icon we want, as a React element, to the button. We can test using the imported icons from the react-feather package
  • The IconButton component should render the icon in the appropriate slot

Code Playground

import React from 'react';
import {
Award,
Camera,
Frown,
Slash,
XCircle,
} from 'react-feather';

import IconButton from './IconButton';

function App() {
// TODO: Render an “IconButton”.
}

export default App;

Solution:

Stretch Goal: Restricting control

So, as we saw at the end of the solution video, it's not ideal that the consumer has so much control over the icon.

For example, there's nothing stopping them from doing this:

<IconButton
icon={
<Frown size={128} />
}
>
Rate Our Product
</IconButton>
Our IconButton but with a huge icon

Alternatively, what if we want to "hardcode" certain props on the provided element?

For example, I personally feel it looks better when the icons are drawn with a slightly thinner line:

<IconButton
icon={
<Frown strokeWidth={1.5} />
}
>
Rate Our Product
</IconButton>
Before:Icon button with thick icon lines
After:Icon button with normal icon lines

The problem here is that we need the consumers to always remember to apply this prop. I don't think that's a reasonable burden to place on them. The IconButton should be the one specifying how large the icon should be!

So, in this stretch goal, your mission is to come up a way to satisfy these conditions:

Acceptance Criteria:

  • The IconButton should still have an icon prop, which gives it an icon to render. IconButton should not be the one importing the icons from "react-feather".
  • IconButton should have 100% control over the props being applied to the icon.

I don't expect you to be able to solve this. It's a challenging exercise, and I haven't shown you how to solve it. But I think it will be helpful if you spend a few moments experimenting, and seeing what you can come up with.

Code Playground

import React from 'react';
import {
Award,
Camera,
Frown,
Slash,
XCircle,
} from 'react-feather';

import IconButton from './IconButton';

function App() {
return (
<>
<IconButton icon={<Award />}>
Collect Award
</IconButton>
<IconButton icon={<Frown />}>
Rate Our Product
</IconButton>
<IconButton icon={<XCircle />}>
Dismiss
</IconButton>
</>
);
}

export default App;

Solution: